/*
 * src/pl/plpython/plpy_procedure.h
 */

#ifndef PLPY_PROCEDURE_H
#define PLPY_PROCEDURE_H

#include "plpy_typeio.h"


extern void init_procedure_caches(void);


/* 外部递归级别或返回集合的函数的保存参数 */
typedef struct PLySavedArgs
{
	struct PLySavedArgs *next;	/* 链表指针 */
	PyObject   *args;			/* globals 字典的 "args" 元素 */
	PyObject   *td;				/* globals 字典的 "TD" 元素，如果是触发器的话 */
	int			nargs;			/* 命名参数数组的长度 */
	PyObject   *namedargs[FLEXIBLE_ARRAY_MEMBER];	/* 命名参数 */
} PLySavedArgs;

/* 缓存的过程数据 */
typedef struct PLyProcedure
{
	MemoryContext mcxt;			/* 持有该 PLyProcedure 及其附属数据的上下文 */
	char	   *proname;		/* 过程的 SQL 名称 */
	char	   *pyname;			/* 过程的 Python 名称 */
	TransactionId fn_xmin;
	ItemPointerData fn_tid;
	bool		fn_readonly;
	bool		is_setof;		/* 如果函数返回结果集则为真 */
	bool		is_procedure;
	bool		is_trigger;		/* 是否作为触发器调用？ */
	PLyObToDatum result;		/* 函数结果输出转换信息 */
	PLyDatumToOb result_in;		/* 用于在触发器中转换输入元组 */
	char	   *src;			/* 文本过程代码，经过修改后 */
	char	  **argnames;		/* 参数名称 */
	PLyDatumToOb *args;			/* 参数输入转换信息 */
	int			nargs;			/* 上述数组中的元素数量 */
	Oid			langid;			/* plpython pg_language 条目的 OID */
	List	   *trftypes;		/* 转换类型的 OID 列表 */
	PyObject   *code;			/* 编译后的过程代码 */
	PyObject   *statics;		/* 在调用之间保存的数据，本地范围 */
	PyObject   *globals;		/* 在调用之间保存的数据，全局范围 */
	long		calldepth;		/* 函数的递归调用深度 */
	PLySavedArgs *argstack;		/* 外层调用参数的堆栈 */
} PLyProcedure;

/* 过程缓存关键字 */
typedef struct PLyProcedureKey
{
	Oid			fn_oid;			/* 函数 OID */
	Oid			fn_rel;			/* 触发的关系或无效的 OID */
} PLyProcedureKey;

/* 过程缓存条目 */
typedef struct PLyProcedureEntry
{
	PLyProcedureKey key;		/* 哈希键 */
	PLyProcedure *proc;
} PLyProcedureEntry;

/* PLyProcedure 操作 */
extern char *PLy_procedure_name(PLyProcedure *proc);
extern PLyProcedure *PLy_procedure_get(Oid fn_oid, Oid fn_rel, bool is_trigger);
extern void PLy_procedure_compile(PLyProcedure *proc, const char *src);
extern void PLy_procedure_delete(PLyProcedure *proc);

#endif							/* PLPY_PROCEDURE_H */
